from datetime import datetime
from zoneinfo import ZoneInfo

import orjson
from fastapi.encoders import jsonable_encoder
from pydantic import root_validator
import inspect
from pydantic import BaseModel

from afast_core.core_tools.datetime_helper import convert_datetime_to_gmt


def orjson_dumps(v, *, default):
    return orjson.dumps(v, default=default).decode()



def optional(*fields):
    def dec(_cls):
        for field in fields:
            _cls.__fields__[field].required = False
        return _cls

    if fields and inspect.isclass(fields[0]) and issubclass(fields[0], BaseModel):
        cls = fields[0]
        fields = cls.__fields__
        return dec(cls)
    return dec


class PydanticBaseModel(BaseModel):

    # def __new__(cls, *args, **kwargs):
    #     # 对当前__fields__重新进行排序
    #     instance = super().__new__(cls)
    #     # 对当前__fields__重新进行排序
    #     cls.__fields__ = {key: cls.__fields__[key] for key in sorted(cls.__fields__.keys())}
    #     return instance

    class Config:
        json_loads = orjson.loads
        json_dumps = orjson_dumps
        json_encoders = {
            datetime: convert_datetime_to_gmt
        }  # method for customer JSON encoding of datetime fields

    # 自定方法进行覆盖
    def dict(self, *args, **kwargs):
        if kwargs and kwargs.get("exclude_none") is not None:
            kwargs["exclude_unset"] = True
        return BaseModel.dict(self, *args, **kwargs)

    # 自定方法进行覆盖进行排序输出
    def dict_sorted(self, *args, **kwargs):
        '''
        字段字段排序输出处理
        :param args:
        :param kwargs:
        :return:
        '''
        return {key: value for key, value in sorted(self.dict(*args, **kwargs).items())}

    @root_validator()
    def set_null_microseconds(cls, data: dict) -> dict:
        """Drops microseconds in all the datetime field values."""
        datetime_fields = {
            k: v.replace(microsecond=0)
            for k, v in data.items()
            if isinstance(k, datetime)
        }

        return {**data, **datetime_fields}

    def serializable_dict(self, **kwargs):
        """Return a dict which contains only serializable fields."""
        default_dict = super().dict(**kwargs)
        return jsonable_encoder(default_dict)



if __name__ == '__main__':
    class sdsa(PydanticBaseModel):
        bsadsad = '43333333333'
        asdkasd = '1111'
        sorted = True


    sdsaaaaaaaaaaaaa = sdsa()
    print(sdsaaaaaaaaaaaaa.serializable_dict())
